/*
   DEOServerMonitor.m created by enoyau on Fri 13-Jan-1995

   You may freely copy, distribute, and reuse the code in this example.
   NeXT disclaims any warranty of any kind, expressed or implied, as to its
   fitness for any particular use.
*/

#import "DEOServerMonitor.h"
#import <foundation/NSNotification.h>
#import <foundation/NSAutoreleasePool.h>
#import <foundation/NSUtilities.h>
#import <foundation/NSBundle.h>
#import <foundation/NSException.h>
#import <remote/NXConnection.h>
#import <remote/NXProxy.h>

#import <libc.h>

static id instance = nil;
NSString *DEOServerReinitialize = @"DEOServerReinitialize";

@implementation DEOServerMonitor

- (id <DEOServer>)server
{
    if(server) return server;

    if(wantLog) NSLog(@"DEOClient: try to connect to the server...\n");
    // Work around for bug (release note reference 51800):
    // This object is coming back retained instead of autoreleased,
    // so we don't send it retain here.
    server = (id <DEOServer>)[NXConnection connectToName:DEOServerName
                                                  onHost:"*"];

    if(!server) {
        NSString *path = [[NSBundle mainBundle] pathForResource:@"DEOServer"
                                                          ofType:nil];
        int pid;

        if(wantLog) NSLog(@"DEOClient: fork a new server\n");

        if((pid = fork()) == 0  ) { // fork the server
            (void)execlp([path cString], [path cString], (char *)0);
            exit(0); // if exec fail...

        } else if(pid != -1) { // try to reconnect
            char here[1024];
            int retry = 20;

            gethostname(here, 1024);

            while((retry--) && (!server)) {
                sleep(1);
                if(wantLog) NSLog(@"DEOClient: try to connect to the new server...\n");
                // Work around for bug (release note reference 51800):
                // see above.
                server = (id <DEOServer>)[NXConnection connectToName:DEOServerName onHost:here];
            }
        }
    }

    if(server) {
        NXConnection *myConnection;

        if(wantLog) NSLog(@"DEOClient: run the connection");
        [(NXProxy *)server setProtocolForProxy:@protocol(DEOServer)];

        myConnection = [(NXProxy*)server connectionForProxy];
        [myConnection registerForInvalidationNotification:self];
        [myConnection runFromAppKit];
    } else {
        if(wantLog) NSLog(@"DEOClient: connection failed\n");
    }

    return server;
}

+ serverMonitor
{
    return [(instance ? [instance retain] : (instance = [self new])) autorelease];
}

- (void)dealloc
{
    NXConnection *myConnection = [(NXProxy*)server connectionForProxy];

    [myConnection unregisterForInvalidationNotification:self];
    NS_DURING
        [(NSObject *)server release];
    NS_HANDLER
        NSLog(@"Failed to send release to server.\n");
    NS_ENDHANDLER
    server = nil;
    instance = nil;
    [super dealloc];
}

- senderIsInvalid:sender
{
    if(wantLog) NSLog(@"DEOClient: Server dead !\n");
    server = nil;
    [[NSNotificationCenter defaultCenter] postNotificationName:DEOServerReinitialize object:self];
    return self;
}

@end
